package org.cimbar.camerafilecopy.wol;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.Toast;
import android.widget.ToggleButton;

import androidx.annotation.NonNull;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
import java.io.FileOutputStream;
import java.io.IOException;
import android.webkit.MimeTypeMap;


public class MainActivity extends Activity implements CvCameraViewListener2 {
    private static final String TAG = "MainActivity";
    private static final int CAMERA_PERMISSION_REQUEST = 1;
    private static final int CREATE_FILE = 11;

    private CameraBridgeViewBase mOpenCvCameraView;
    private ToggleButton mModeSwitch;
    private int modeVal = 0;
    private int detectedMode = 68;
    private String dataPath;
    private String activePath;
    private boolean disclaimerAccepted = false;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            if (status == LoaderCallbackInterface.SUCCESS) {
                Log.i(TAG, "OpenCV loaded successfully");

                // Load native library after(!) OpenCV initialization
                System.loadLibrary("cfc-cpp");

                mOpenCvCameraView.enableView();
            } else {
                super.onManagerConnected(status);
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);

        // 设置基本布局
        setContentView(R.layout.activity_main);
        
        // 初始化相机视图但先隐藏
        mOpenCvCameraView = findViewById(R.id.main_surface);
        mOpenCvCameraView.setVisibility(SurfaceView.GONE);
        
        // 每次启动都显示免责声明
        showDisclaimerDialog();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == CAMERA_PERMISSION_REQUEST) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                mOpenCvCameraView.setCameraPermissionGranted();
            } else {
                String message = "相机权限未许可";
                Log.e(TAG, message);
                Toast.makeText(this, message, Toast.LENGTH_LONG).show();
            }
        } else {
            Log.e(TAG, "Unexpected permission request");
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Toast.makeText(this, "Encode data at https://gitee.com/ddocan/colorcode-express-for-pc! :)",  Toast.LENGTH_LONG).show();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (isDisclaimerAccepted())
            mOpenCvCameraView.disableView();
    
        // 不在onPause中退出应用，因为这可能在很多情况下被触发
        // 只在onStop中退出应用，这更准确地表示应用进入后台
    }

    @Override
    public void onStop() {
        super.onStop();
        if (isDisclaimerAccepted())
            mOpenCvCameraView.disableView();
    
        // 应用最小化时彻底退出
        cleanupAndFinish();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (isDisclaimerAccepted()) {
            mOpenCvCameraView.enableView();
        }
        // 不需要在这里重置状态，因为每次都是全新的开始
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (isDisclaimerAccepted())
            mOpenCvCameraView.disableView();
    
        // 确保清理所有临时文件
        cleanupTemporaryFiles();
    
        // 可以考虑调用native清理方法
        try {
            shutdownJNI();
        } catch (UnsatisfiedLinkError e) {
            Log.w(TAG, "Native library not loaded or shutdownJNI not implemented");
        }
    }

    // 确保在finish时也清理文件
    private void cleanupTemporaryFiles() {
        try {
            // 删除解压目录
            String extractDirPath = dataPath + "/extracted/";
            File extractDir = new File(extractDirPath);
            if (extractDir.exists()) {
                deleteRecursive(extractDir);
            }
            
            // 删除临时文件（如果有）
            if (activePath != null) {
                File activeFile = new File(activePath);
                if (activeFile.exists()) {
                    activeFile.delete();
                }
                activePath = null;
            }
            
            Log.d(TAG, "Cleaned up temporary files");
        } catch (Exception e) {
            Log.e(TAG, "Error cleaning up temporary files: " + e.getMessage());
        }
    }

    @Override
    public void onCameraViewStarted(int width, int height) {
    }

    @Override
    public void onCameraViewStopped() {
    }

    @Override
    public Mat onCameraFrame(CvCameraViewFrame frame) {
        // get current camera frame as OpenCV Mat object
        Mat mat = frame.rgba();

        // native call to process current camera frame
        String res = processImageJNI(mat.getNativeObjAddr(), this.dataPath, this.modeVal);

        // res will contain a file path if we completed a transfer. Ask the user where to save it
        if (res.startsWith("/")) {
            if (res.length() >= 2 && res.charAt(1) == '4') {
                detectedMode = 4;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mModeSwitch.setActivated(true);
                        mModeSwitch.setChecked(true);
                    }
                });
            }
            else {
                detectedMode = 68;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mModeSwitch.setActivated(false);
                        mModeSwitch.setChecked(true);
                    }
                });
            }

        }
        else if (!res.isEmpty()) {
            // 每次都是全新开始，不需要检查是否重复处理
            // 生成以当前日期时间命名的临时文件
//            Log.d(TAG, "res path："+res);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String currentDateAndTime = sdf.format(new Date());
            String tempFileName = currentDateAndTime + "temp";

            // 保存原始文件路径
            this.activePath = this.dataPath + "/" + res;

            // 重命名为日期+temp格式
            File originalFile = new File(this.activePath);
            File tempFile = new File(this.dataPath + "/" + tempFileName);
            if (originalFile.exists()) {
                originalFile.renameTo(tempFile);
                this.activePath = tempFile.getAbsolutePath();
            }

            // 自动解压ZIP文件并分享
            unzipAndShareFile(this.activePath);

        }

        // return processed frame for live preview
        return mat;
    }


    private void unzipAndShareFile(String filePath) {
        new Thread(() -> {
            try {
//                Log.d(TAG, "Starting unzip process for file: " + filePath);
                // 重命名为.zip文件
                File originalFile = new File(filePath);
                String zipFileName = filePath + ".zip";
                File zipFile = new File(zipFileName);
                if (originalFile.exists()) {
                    originalFile.renameTo(zipFile);
//                    Log.d(TAG, "Renamed file to: " + zipFileName);
                }

                // 解压ZIP文件
                String extractDir = dataPath + "/extracted/";
                File extractDirFile = new File(extractDir);
                if (!extractDirFile.exists()) {
                    extractDirFile.mkdirs();
                }

                // 使用指定的UTF-8编码解压ZIP文件
                String extractedFilePath = "";
                Log.d(TAG, "Using UTF-8 encoding for ZIP file extraction");
                
                try (FileInputStream fis = new FileInputStream(zipFile);
                     ZipInputStream zis = new ZipInputStream(fis, java.nio.charset.StandardCharsets.UTF_8)) {
                    
                    ZipEntry zipEntry;
                    while ((zipEntry = zis.getNextEntry()) != null) {
                        String entryName = zipEntry.getName();
//                        Log.d(TAG, "Entry name with UTF-8: " + entryName);

                        File newFile = new File(extractDir, entryName);
                        if (zipEntry.isDirectory()) {
                            if (!newFile.isDirectory() && !newFile.mkdirs()) {
                                throw new IOException("Failed to create directory " + newFile);
                            }
                        } else {
                            File parent = newFile.getParentFile();
                            if (parent != null && !parent.isDirectory() && !parent.mkdirs()) {
                                throw new IOException("Failed to create directory " + parent);
                            }

                            try (FileOutputStream fos = new FileOutputStream(newFile)) {
                                byte[] buffer = new byte[8192];
                                int len;
                                while ((len = zis.read(buffer)) > 0) {
                                    fos.write(buffer, 0, len);
                                }
                            }
                            extractedFilePath = newFile.getAbsolutePath();
//                            Log.d(TAG, "Extracted file path: " + extractedFilePath);
                        }
                        zis.closeEntry();
                    }
                    Log.d(TAG, "Successfully extracted with UTF-8 encoding");
                } catch (Exception e) {
                    Log.e(TAG, "Failed to extract with UTF-8 encoding: " + e.getMessage(), e);
                    throw e; // 重新抛出异常，让外层catch处理
                }

                // 删除临时ZIP文件
                zipFile.delete();
                Log.d(TAG, "Deleted temporary zip file");

                // 分享解压后的文件
                String finalExtractedFilePath = extractedFilePath;
//                Log.d(TAG, "About to share file: " + finalExtractedFilePath);
                runOnUiThread(() -> shareFile(finalExtractedFilePath));

            } catch (Exception e) {
                Log.e(TAG, "Error unzipping file: " + e.getMessage(), e);
                runOnUiThread(() -> Toast.makeText(this, "解压文件失败: " + e.getMessage(), Toast.LENGTH_LONG).show());
            }
        }).start();
    }

    private void shareFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();
            return;
        }

        Uri fileUri = androidx.core.content.FileProvider.getUriForFile(
                this,
                getApplicationContext().getPackageName() + ".provider",
                file);

        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        // 使用系统工具自动推断MIME类型
        String extension = MimeTypeMap.getFileExtensionFromUrl(file.getAbsolutePath());
        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
        if(mimeType == null){
            mimeType = getMimeType(file);;
        }
        shareIntent.setType(mimeType != null ? mimeType : "*/*");

        // 添加文件名信息，确保大部分应用能正确识别文件名
        shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
        shareIntent.putExtra(Intent.EXTRA_SUBJECT, file.getName());
        shareIntent.putExtra(Intent.EXTRA_TITLE, file.getName());

        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        // 使用 startActivityForResult 来监听分享结果
        startActivityForResult(Intent.createChooser(shareIntent, "选择应用打开文件"), 1001);
    }

    // 根据文件扩展名获取MIME类型
    private String getMimeType(File file) {
        String fileName = file.getName().toLowerCase();
        if (fileName.endsWith(".png")) {
            return "image/png";
        } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (fileName.endsWith(".gif")) {
            return "image/gif";
        } else if (fileName.endsWith(".bmp")) {
            return "image/bmp";
        } else if (fileName.endsWith(".webp")) {
            return "image/webp";
        } else if (fileName.endsWith(".txt")) {
            return "text/plain";
        } else if (fileName.endsWith(".pdf")) {
            return "application/pdf";
        } else if (fileName.endsWith(".doc")) {
            return "application/msword";
        } else if (fileName.endsWith(".docx")) {
            return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        } else if (fileName.endsWith(".xls")) {
            return "application/vnd.ms-excel";
        } else if (fileName.endsWith(".xlsx")) {
            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        } else if (fileName.endsWith(".ppt")) {
            return "application/vnd.ms-powerpoint";
        } else if (fileName.endsWith(".pptx")) {
            return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
        } else if (fileName.endsWith(".zip")) {
            return "application/zip";
        } else if (fileName.endsWith(".rar")) {
            return "application/x-rar-compressed";
        } else if (fileName.endsWith(".7z")) {
            return "application/x-7z-compressed";
        }
        return null;
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        // 当分享操作完成后，清理临时文件并退出应用
        if (requestCode == 1001) {
            // 在新线程中清理所有临时文件
            new Thread(() -> {
                try {
                    // 删除解压目录
                    String extractDirPath = dataPath + "/extracted/";
                    File extractDir = new File(extractDirPath);
                    if (extractDir.exists()) {
                        deleteRecursive(extractDir);
                    }
                    
                    // 删除临时文件（如果有）
                    if (activePath != null) {
                        File activeFile = new File(activePath);
                        if (activeFile.exists()) {
                            activeFile.delete();
                        }
                    }
                    
//                    Log.d(TAG, "Cleaned up temporary files");
                } catch (Exception e) {
                    Log.e(TAG, "Error cleaning up temporary files: " + e.getMessage());
                }
            }).start();

            // 关闭应用程序并彻底清理
            cleanupAndFinish();
        }
    }
    
    /**
     * 递归删除文件或目录
     */
    private void deleteRecursive(File fileOrDirectory) {
        if (fileOrDirectory.isDirectory()) {
            File[] files = fileOrDirectory.listFiles();
            if (files != null) {
                for (File child : files) {
                    deleteRecursive(child);
                }
            }
        }
        fileOrDirectory.delete();
    }
    
    private native String processImageJNI(long mat, String path, int modeInt);
    private native void shutdownJNI();

    private void showDisclaimerDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.disclaimer_title);
        builder.setMessage(R.string.disclaimer_text);
        builder.setCancelable(false);
        builder.setPositiveButton(R.string.agree, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                disclaimerAccepted = true;
                initializeApp();
            }
        });
        builder.setNegativeButton(R.string.disagree, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                finish();
            }
        });
        AlertDialog dialog = builder.create();
        dialog.show();

        // 使按钮靠向两边
        android.widget.Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
        android.widget.Button negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);

        // 设置按钮靠向两边
        if (positiveButton != null && negativeButton != null) {
            // 设置负按钮（不同意）靠左
            android.widget.LinearLayout.LayoutParams negativeParams = (android.widget.LinearLayout.LayoutParams) negativeButton.getLayoutParams();
            negativeParams.weight = 25;
            negativeParams.gravity = android.view.Gravity.START;
            negativeButton.setLayoutParams(negativeParams);

            // 设置正按钮（同意）靠右
            android.widget.LinearLayout.LayoutParams positiveParams = (android.widget.LinearLayout.LayoutParams) positiveButton.getLayoutParams();
            positiveParams.weight = 25;
            positiveParams.gravity = android.view.Gravity.END;
            positiveButton.setLayoutParams(positiveParams);
        }
    }

    private void initializeApp() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        // Permissions for Android 6+
        ActivityCompat.requestPermissions(
                this,
                new String[]{Manifest.permission.CAMERA},
                CAMERA_PERMISSION_REQUEST
        );

        this.dataPath = this.getFilesDir().getPath();

        // 初始化OpenCV
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
        
        // 设置相机视图可见并添加监听器
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        
        // 初始化模式切换按钮
        mModeSwitch = (ToggleButton) findViewById(R.id.mode_switch);
        if (mModeSwitch != null) {
            mModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (isChecked) {
                        modeVal = detectedMode;
                    } else {
                        modeVal = 0;
                    }
                }
            });
        }
    }

    private boolean isDisclaimerAccepted() {
        return disclaimerAccepted && mOpenCvCameraView != null;
    }
    
    private void cleanupAndFinish() {
        // 清理临时文件
        try {
            // 删除解压目录
            String extractDirPath = dataPath + "/extracted/";
            File extractDir = new File(extractDirPath);
            if (extractDir.exists()) {
                deleteRecursive(extractDir);
            }
            
            // 删除临时文件（如果有）
            if (activePath != null) {
                File activeFile = new File(activePath);
                if (activeFile.exists()) {
                    activeFile.delete();
                }
                activePath = null;
            }
        } catch (Exception e) {
            Log.e(TAG, "Error cleaning up temporary files: " + e.getMessage());
        }
        
        // 尝试彻底关闭应用
        try {
            // 调用native清理方法
            try {
                shutdownJNI();
            } catch (UnsatisfiedLinkError e) {
                Log.w(TAG, "Native library not loaded or shutdownJNI not implemented");
            }
            
            // 请求系统关闭该Activity
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                finishAffinity();
            }
            
            // 尝试多种方法确保应用退出
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                finishAndRemoveTask();
            } else {
                finish();
            }
            
        } catch (Exception e) {
            Log.e(TAG, "Error finishing activity: " + e.getMessage());
        } finally {
            // 最后的手段 - 延迟杀死进程以确保其他清理操作完成
            new android.os.Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    android.os.Process.killProcess(android.os.Process.myPid());
                }
            }, 100); // 延迟100毫秒确保清理完成
        }
    }
}